/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#undef LOG_TAG
#define LOG_TAG "AudioAdapterManager"

#include "audio_adapter_manager.h"

#include <memory>
#include <unistd.h>

#include "parameter.h"
#include "parameters.h"
#include "setting_provider.h"

#include "audio_errors.h"
#include "audio_log.h"
#include "audio_volume_parser.h"

using namespace std;

namespace OHOS {
namespace AudioStandard {
static const std::vector<AudioStreamType> VOLUME_TYPE_LIST = {
    // all volume types except STREAM_ALL
    STREAM_MUSIC,
    STREAM_RING,
    STREAM_VOICE_CALL,
    STREAM_VOICE_ASSISTANT,
    STREAM_ALARM,
    STREAM_ACCESSIBILITY,
    STREAM_ULTRASONIC
};

static const std::vector<DeviceType> DEVICE_TYPE_LIST = {
    // The three devices represent the three volume groups(build-in, wireless, wired).
    DEVICE_TYPE_SPEAKER,
    DEVICE_TYPE_BLUETOOTH_A2DP,
    DEVICE_TYPE_WIRED_HEADSET
};

static const std::vector<AudioStreamType> VOICE_CALL_VOLUME_TYPE_LIST = {
    // all stream types for voice call volume type
    STREAM_VOICE_CALL,
    STREAM_VOICE_MESSAGE,
    STREAM_VOICE_COMMUNICATION
};

static const std::vector<AudioStreamType> RINGTONE_VOLUME_TYPE_LIST = {
    // all stream types for ringtone volume type
    STREAM_RING,
    STREAM_SYSTEM,
    STREAM_NOTIFICATION,
    STREAM_SYSTEM_ENFORCED,
    STREAM_DTMF
};

static const std::vector<AudioStreamType> MEDIA_VOLUME_TYPE_LIST = {
    // all stream types for media volume type
    STREAM_MUSIC,
    STREAM_MOVIE,
    STREAM_GAME,
    STREAM_SPEECH,
    STREAM_NAVIGATION
};

static const std::vector<std::string> SYSTEM_SOUND_KEY_LIST = {
    // all keys for system sound uri
    "ringtone_for_sim_card_0",
    "ringtone_for_sim_card_1",
    "system_tone_for_sim_card_0",
    "system_tone_for_sim_card_1",
    "system_tone_for_notification"
};

bool AudioAdapterManager::Init()
{
    char testMode[10] = {0}; // 10 for system parameter usage
    auto res = GetParameter("debug.audio_service.testmodeon", "0", testMode, sizeof(testMode));
    if (res == 1 && testMode[0] == '1') {
        AUDIO_DEBUG_LOG("testMode on");
        testModeOn_ = true;
    }

    std::unique_ptr<AudioVolumeParser> audiovolumeParser = make_unique<AudioVolumeParser>();
    if (!audiovolumeParser->LoadConfig(streamVolumeInfos_)) {
        AUDIO_INFO_LOG("Audio Volume Config Load Configuration successfully");
        useNonlinearAlgo_ = 1;
        UpdateVolumeMapIndex();
    }

    // init volume before kvstore start by local prop for bootanimation
    char currentVolumeValue[3] = {0};
    auto ret = GetParameter("persist.multimedia.audio.ringtonevolume", "7",
        currentVolumeValue, sizeof(currentVolumeValue));
    if (ret > 0) {
        int32_t ringtoneVolumeLevel = atoi(currentVolumeValue);
        volumeLevelMap_[STREAM_RING] = ringtoneVolumeLevel;
        AUDIO_INFO_LOG("Init: Get ringtone volume to map success %{public}d", volumeLevelMap_[STREAM_RING]);
    } else {
        AUDIO_ERR_LOG("Init: Get volume parameter failed %{public}d", ret);
    }

    isVolumeUnadjustable_ = system::GetBoolParameter("const.multimedia.audio.fixedvolume", false);
    AUDIO_INFO_LOG("Get fixdvolume parameter success %{public}d", isVolumeUnadjustable_);

    return true;
}

bool AudioAdapterManager::ConnectServiceAdapter()
{
    std::unique_ptr<PolicyCallbackImpl> policyCallbackImpl = std::make_unique<PolicyCallbackImpl>(this);
    audioServiceAdapter_ = AudioServiceAdapter::CreateAudioAdapter(std::move(policyCallbackImpl));
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, false,
        "[AudioAdapterManager] Error in audio adapter initialization");

    bool result = audioServiceAdapter_->Connect();
    CHECK_AND_RETURN_RET_LOG(result, false, "[AudioAdapterManager] Error in connecting audio adapter");

    return true;
}

void AudioAdapterManager::InitKVStore()
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    InitKVStoreInternal();
}

void AudioAdapterManager::InitKVStoreInternal()
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ == nullptr, "InitKVStore: kv store is not nullptr.");

    AUDIO_INFO_LOG("AudioAdapterManager::%{public}s in", __func__);
    bool isFirstBoot = false;
    InitAudioPolicyKvStore(isFirstBoot);
    InitVolumeMap(isFirstBoot);
    InitRingerMode(isFirstBoot);
    InitMuteStatusMap(isFirstBoot);

    // Make sure that the volume value is applied.
    auto iter = VOLUME_TYPE_LIST.begin();
    while (iter != VOLUME_TYPE_LIST.end()) {
        SetVolumeDb(*iter);
        iter++;
    }
}

int32_t AudioAdapterManager::ReInitKVStore()
{
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, ERR_INVALID_OPERATION,
        "audioPolicyKvStore_ is already nullptr");
    audioPolicyKvStore_ = nullptr;
    DistributedKvDataManager manager;
    Options options;

    AppId appId;
    appId.appId = "audio_policy_manager";
    options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId;

    StoreId storeId;
    storeId.storeId = "audiopolicy";
    Status status = Status::SUCCESS;

    status = manager.CloseKvStore(appId, storeId);
    AUDIO_ERR_LOG("CloseKvStore status: %{public}d", status);
    CHECK_AND_RETURN_RET_LOG(status == Status::SUCCESS, ERR_ILLEGAL_STATE, "CloseKvStore failed!");

    status = manager.DeleteKvStore(appId, storeId, options.baseDir);
    CHECK_AND_RETURN_RET_LOG(status == Status::SUCCESS, ERR_ILLEGAL_STATE, "CloseKvStore failed!");

    InitKVStoreInternal();
    return SUCCESS;
}

void AudioAdapterManager::Deinit(void)
{
    CHECK_AND_RETURN_LOG(audioServiceAdapter_, "Deinit audio adapter null");

    return audioServiceAdapter_->Disconnect();
}

int32_t AudioAdapterManager::SetAudioSessionCallback(AudioSessionCallback *callback)
{
    CHECK_AND_RETURN_RET_LOG(callback != nullptr, ERR_INVALID_PARAM,
        "SetAudioSessionCallback callback == nullptr");

    sessionCallback_ = callback;
    return SUCCESS;
}

int32_t AudioAdapterManager::GetMaxVolumeLevel(AudioVolumeType volumeType)
{
    CHECK_AND_RETURN_RET_LOG(volumeType >= STREAM_VOICE_CALL && volumeType <= STREAM_TYPE_MAX,
        ERR_INVALID_PARAM, "Invalid stream type");
    return maxVolumeIndexMap_[volumeType];
}

int32_t AudioAdapterManager::GetMinVolumeLevel(AudioVolumeType volumeType)
{
    CHECK_AND_RETURN_RET_LOG(volumeType >= STREAM_VOICE_CALL && volumeType <= STREAM_TYPE_MAX,
        ERR_INVALID_PARAM, "Invalid stream type");
    return minVolumeIndexMap_[volumeType];
}

void AudioAdapterManager::SaveRingtoneVolumeToLocal(AudioVolumeType volumeType, int32_t volumeLevel)
{
    if (volumeType == STREAM_RING) {
        int32_t ret = SetParameter("persist.multimedia.audio.ringtonevolume", std::to_string(volumeLevel).c_str());
        if (ret == 0) {
            AUDIO_INFO_LOG("Save ringtone volume for boot success %{public}d", volumeLevel);
        } else {
            AUDIO_ERR_LOG("Save ringtone volume for boot failed, result %{public}d", ret);
        }
    }
}

int32_t AudioAdapterManager::SetSystemVolumeLevel(AudioStreamType streamType, int32_t volumeLevel,
    bool /* isFromVolumeKey */)
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    AUDIO_INFO_LOG("SetSystemVolumeLevel: streamType: %{public}d, deviceType: %{public}d, volumeLevel:%{public}d",
        streamType, currentActiveDevice_, volumeLevel);
    if (volumeLevel == 0 &&
        (streamType == STREAM_VOICE_ASSISTANT || streamType == STREAM_VOICE_CALL ||
        streamType == STREAM_ALARM || streamType == STREAM_ACCESSIBILITY ||
        streamType == STREAM_VOICE_COMMUNICATION)) {
        // these types can not set to mute, but don't return error
        AUDIO_ERR_LOG("SetSystemVolumeLevel this type can not set mute");
        return SUCCESS;
    }
    int32_t mimRet = GetMinVolumeLevel(streamType);
    int32_t maxRet = GetMaxVolumeLevel(streamType);
    CHECK_AND_RETURN_RET_LOG(volumeLevel >= mimRet && volumeLevel <= maxRet, ERR_OPERATION_FAILED,
        "volumeLevel not in scope.");

    // In case if KvStore didnot connect during bootup
    if (audioPolicyKvStore_ == nullptr) {
        InitKVStoreInternal();
    }

    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);
    volumeLevelMap_[streamForVolumeMap] = volumeLevel;
    WriteVolumeToKvStore(currentActiveDevice_, streamType, volumeLevel);

    UpdateRingerModeForVolume(streamType, volumeLevel);

    UpdateMuteStatusForVolume(streamType, volumeLevel);

    return SetVolumeDb(streamType);
}

void AudioAdapterManager::UpdateRingerModeForVolume(AudioStreamType streamType, int32_t volumeLevel)
{
    //The ringer mode is automatically updated based on the ringtone volume
    if (streamType != STREAM_RING) {
        return;
    }
    if (volumeLevel > 0 && (ringerMode_ == RINGER_MODE_SILENT || ringerMode_ == RINGER_MODE_VIBRATE)) {
        // ringtone volume > 0, change the ringer mode to RINGER_MODE_NORMAL
        SetRingerModeInternal(RINGER_MODE_NORMAL);
    } else if (volumeLevel == 0 && ringerMode_ == RINGER_MODE_NORMAL) {
        // ringtone volume == 0, change the ringer mode to RINGER_MODE_VIBRATE
        SetRingerModeInternal(RINGER_MODE_VIBRATE);
    }
}

void AudioAdapterManager::UpdateMuteStatusForVolume(AudioStreamType streamType, int32_t volumeLevel)
{
    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);

    //The mute status is automatically updated based on the stream volume
    if (volumeLevel > 0 && GetStreamMuteInternal(streamType)) {
        muteStatusMap_[streamForVolumeMap] = false;
        WriteMuteStatusToKvStore(currentActiveDevice_, streamType, false);
    } else if (volumeLevel == 0 && !GetStreamMuteInternal(streamType)) {
        muteStatusMap_[streamForVolumeMap] = true;
        WriteMuteStatusToKvStore(currentActiveDevice_, streamType, true);
    }
}

int32_t AudioAdapterManager::SetVolumeDb(AudioStreamType streamType)
{
    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);
    int32_t volumeLevel = volumeLevelMap_[streamForVolumeMap] * (muteStatusMap_[streamForVolumeMap] ? 0 : 1);

    // Save volume in local prop for bootanimation
    SaveRingtoneVolumeToLocal(streamForVolumeMap, volumeLevel);

    float volumeDb = 1.0f;
    if (useNonlinearAlgo_) {
        volumeDb = CalculateVolumeDbNonlinear(streamType, currentActiveDevice_, volumeLevel);
    } else {
        volumeDb = CalculateVolumeDb(volumeLevel);
    }

    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "SetSystemVolumeLevel audio adapter null");

    AUDIO_INFO_LOG("SetVolumeDb: streamType %{public}d, volumeDb %{public}f", streamType, volumeDb);
    if (streamType == STREAM_VOICE_CALL || streamType == STREAM_VOICE_COMMUNICATION) {
        return SetVolumeDbForVolumeTypeGroup(VOICE_CALL_VOLUME_TYPE_LIST, volumeDb);
    } else if (streamType == STREAM_MUSIC) {
        return SetVolumeDbForVolumeTypeGroup(MEDIA_VOLUME_TYPE_LIST, volumeDb);
    } else if (streamType == STREAM_RING) {
        return SetVolumeDbForVolumeTypeGroup(RINGTONE_VOLUME_TYPE_LIST, volumeDb);
    }

    return audioServiceAdapter_->SetVolumeDb(streamType, volumeDb);
}

int32_t AudioAdapterManager::SetVolumeDbForVolumeTypeGroup(const std::vector<AudioStreamType> &volumeTypeGroup,
    float volumeDb)
{
    int32_t result = SUCCESS;
    for (auto &streamType: volumeTypeGroup) {
        result = audioServiceAdapter_->SetVolumeDb(streamType, volumeDb);
        if (result != SUCCESS) {
            // The operation of setting volume has failed, return error directly.
            return result;
        }
    }
    return result;
}

int32_t AudioAdapterManager::GetSystemVolumeLevel(AudioStreamType streamType, bool isFromVolumeKey)
{
    if (!isFromVolumeKey && GetStreamMute(streamType)) {
        return MIN_VOLUME_LEVEL;
    }
    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);

    return volumeLevelMap_[streamForVolumeMap];
}

float AudioAdapterManager::GetSystemVolumeDb(AudioStreamType streamType)
{
    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);

    int32_t volumeLevel = volumeLevelMap_[streamForVolumeMap];
    return CalculateVolumeDb(volumeLevel);
}

int32_t AudioAdapterManager::SetStreamMute(AudioStreamType streamType, bool mute)
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    return SetStreamMuteInternal(streamType, mute);
}

int32_t AudioAdapterManager::SetStreamMuteInternal(AudioStreamType streamType, bool mute)
{
    AUDIO_INFO_LOG("SetStreamMute: stream type %{public}d, mute %{public}d", streamType, mute);
    if (mute &&
        (streamType == STREAM_VOICE_ASSISTANT || streamType == STREAM_VOICE_CALL ||
        streamType == STREAM_ALARM || streamType == STREAM_ACCESSIBILITY ||
        streamType == STREAM_VOICE_COMMUNICATION)) {
        // these types can not set to mute, but don't return error
        AUDIO_ERR_LOG("SetStreamMute: this type can not set mute");
        return SUCCESS;
    }

    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);
    muteStatusMap_[streamForVolumeMap] = mute;
    WriteMuteStatusToKvStore(currentActiveDevice_, streamType, mute);

    if (!mute && volumeLevelMap_[streamForVolumeMap] == 0) {
        AUDIO_INFO_LOG("SetStreamMute: stream type %{public}d is unmuted, but the volume is 0. Set to 1.", streamType);
        volumeLevelMap_[streamForVolumeMap] = 1;
        WriteVolumeToKvStore(currentActiveDevice_, streamType, 1);
    }

    // Achieve the purpose of adjusting the mute status by adjusting the stream volume.
    return SetVolumeDb(streamType);
}

int32_t AudioAdapterManager::SetSourceOutputStreamMute(int32_t uid, bool setMute)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "SetSourceOutputStreamMute audio adapter null");
    return audioServiceAdapter_->SetSourceOutputMute(uid, setMute);
}

bool AudioAdapterManager::GetStreamMute(AudioStreamType streamType)
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    return GetStreamMuteInternal(streamType);
}

bool AudioAdapterManager::GetStreamMuteInternal(AudioStreamType streamType)
{
    AudioStreamType streamForVolumeMap = GetStreamForVolumeMap(streamType);
    return muteStatusMap_[streamForVolumeMap];
}

vector<SinkInfo> AudioAdapterManager::GetAllSinks()
{
    if (!audioServiceAdapter_) {
        AUDIO_ERR_LOG("GetAllSinks audio adapter null");
        vector<SinkInfo> sinkInputList;
        return sinkInputList;
    }

    return audioServiceAdapter_->GetAllSinks();
}

vector<SinkInput> AudioAdapterManager::GetAllSinkInputs()
{
    if (!audioServiceAdapter_) {
        AUDIO_ERR_LOG("GetAllSinkInputs audio adapter null");
        vector<SinkInput> sinkInputList;
        return sinkInputList;
    }

    return audioServiceAdapter_->GetAllSinkInputs();
}

vector<SourceOutput> AudioAdapterManager::GetAllSourceOutputs()
{
    if (!audioServiceAdapter_) {
        AUDIO_ERR_LOG("GetAllSourceOutputs audio adapter null");
        vector<SourceOutput> sourceOutputList;
        return sourceOutputList;
    }

    return audioServiceAdapter_->GetAllSourceOutputs();
}

int32_t AudioAdapterManager::SuspendAudioDevice(std::string &portName, bool isSuspend)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "SuspendAudioDevice audio adapter null");

    return audioServiceAdapter_->SuspendAudioDevice(portName, isSuspend);
}

bool AudioAdapterManager::SetSinkMute(const std::string &sinkName, bool isMute)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, false, "SetSinkMute audio adapter null");

    return audioServiceAdapter_->SetSinkMute(sinkName, isMute);
}

int32_t AudioAdapterManager::SelectDevice(DeviceRole deviceRole, InternalDeviceType deviceType, std::string name)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "SelectDevice audio adapter null");
    switch (deviceRole) {
        case DeviceRole::INPUT_DEVICE:
            return audioServiceAdapter_->SetDefaultSource(name);
        case DeviceRole::OUTPUT_DEVICE: {
            AUDIO_INFO_LOG("SetDefaultSink %{public}d", deviceType);
            return audioServiceAdapter_->SetDefaultSink(name);
        }
        default:
            AUDIO_ERR_LOG("SelectDevice error deviceRole %{public}d", deviceRole);
            return ERR_OPERATION_FAILED;
    }
    return SUCCESS;
}

int32_t AudioAdapterManager::SetDeviceActive(AudioIOHandle ioHandle, InternalDeviceType deviceType,
    std::string name, bool active, DeviceFlag flag)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "SetDeviceActive audio adapter null");

    switch (deviceType) {
        case InternalDeviceType::DEVICE_TYPE_USB_ARM_HEADSET: {
            if (name == USB_SPEAKER) {
                return audioServiceAdapter_->SetDefaultSink(name);
            } else {
                return audioServiceAdapter_->SetDefaultSource(name);
            }
        }
        default: {
            int32_t ret = SUCCESS;
            int32_t errs[2]{SUCCESS, SUCCESS};
            if (IsInputDevice(deviceType) && (flag & INPUT_DEVICES_FLAG)) {
                AUDIO_INFO_LOG("SetDefaultSource %{public}d", deviceType);
                errs[0] = audioServiceAdapter_->SetDefaultSource(name);
                if (errs[0] != SUCCESS) {
                    AUDIO_ERR_LOG("SetDefaultSource err: %{public}d", errs[0]);
                    ret = errs[0];
                }
            }
            if (IsOutputDevice(deviceType) && (flag & OUTPUT_DEVICES_FLAG)) {
                AUDIO_INFO_LOG("SetDefaultSink %{public}d", deviceType);
                errs[1] = audioServiceAdapter_->SetDefaultSink(name);
                if (errs[1] != SUCCESS) {
                    AUDIO_ERR_LOG("SetDefaultSink err: %{public}d", errs[1]);
                    ret = errs[1];
                }
            }
            // Ensure compatibility across different platforms and versions
            if (errs[0] == SUCCESS || errs[1] == SUCCESS) {
                return SUCCESS;
            }
            return ret;
        }
    }
    return SUCCESS;
}

void AudioAdapterManager::SetVolumeForSwitchDevice(InternalDeviceType deviceType)
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    if (GetVolumeGroupForDevice(currentActiveDevice_) == GetVolumeGroupForDevice(deviceType)) {
        AUDIO_INFO_LOG("Old device: %{public}d. New device: %{public}d. No need to update volume",
            currentActiveDevice_, deviceType);
        currentActiveDevice_ = deviceType;
        return;
    }

    AUDIO_INFO_LOG("SetVolumeForSwitchDevice: Load volume and mute status for new device %{public}d", deviceType);
    // Current device must be updated even if kvStore is nullptr.
    currentActiveDevice_ = deviceType;

    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr, "SetVolumeForSwitchDevice audioPolicyKvStore_ is null!");
    LoadVolumeMap();
    LoadMuteStatusMap();

    auto iter = VOLUME_TYPE_LIST.begin();
    while (iter != VOLUME_TYPE_LIST.end()) {
        // update volume level and mute status for each stream type
        SetVolumeDb(*iter);
        AUDIO_INFO_LOG("SetVolumeForSwitchDevice: volume: %{public}d, mute: %{public}d for stream type %{public}d",
            volumeLevelMap_[*iter], muteStatusMap_[*iter], *iter);
        iter++;
    }
}

int32_t AudioAdapterManager::MoveSinkInputByIndexOrName(uint32_t sinkInputId, uint32_t sinkIndex, std::string sinkName)
{
    return audioServiceAdapter_->MoveSinkInputByIndexOrName(sinkInputId, sinkIndex, sinkName);
}

int32_t AudioAdapterManager::MoveSourceOutputByIndexOrName(uint32_t sourceOutputId, uint32_t sourceIndex,
    std::string sourceName)
{
    return audioServiceAdapter_->MoveSourceOutputByIndexOrName(sourceOutputId, sourceIndex, sourceName);
}

int32_t AudioAdapterManager::SetRingerMode(AudioRingerMode ringerMode)
{
    std::lock_guard<std::mutex> lock(muteStatusMutex_);
    return SetRingerModeInternal(ringerMode);
}

int32_t AudioAdapterManager::SetRingerModeInternal(AudioRingerMode ringerMode)
{
    AUDIO_INFO_LOG("SetRingerMode: %{public}d", ringerMode);
    ringerMode_ = ringerMode;

    switch (ringerMode) {
        case RINGER_MODE_SILENT:
        case RINGER_MODE_VIBRATE:
            SetStreamMuteInternal(STREAM_RING, true);
            break;
        case RINGER_MODE_NORMAL:
            SetStreamMuteInternal(STREAM_RING, false);
            break;
        default:
            break;
    }

    // In case if KvStore didnot connect during bootup
    if (audioPolicyKvStore_ == nullptr) {
        InitKVStoreInternal();
    }

    WriteRingerModeToKvStore(ringerMode);
    return SUCCESS;
}

AudioRingerMode AudioAdapterManager::GetRingerMode() const
{
    return ringerMode_;
}

AudioIOHandle AudioAdapterManager::OpenAudioPort(const AudioModuleInfo &audioModuleInfo)
{
    std::string moduleArgs = GetModuleArgs(audioModuleInfo);
    AUDIO_INFO_LOG("[Adapter load-module] %{public}s %{public}s", audioModuleInfo.lib.c_str(), moduleArgs.c_str());

    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_ != nullptr, ERR_OPERATION_FAILED, "ServiceAdapter is null");
    return audioServiceAdapter_->OpenAudioPort(audioModuleInfo.lib, moduleArgs.c_str());
}

AudioIOHandle AudioAdapterManager::LoadLoopback(const LoopbackModuleInfo &moduleInfo)
{
    std::string moduleArgs = GetLoopbackModuleArgs(moduleInfo);
    AUDIO_INFO_LOG("[Adapter load-module] %{public}s %{public}s", moduleInfo.lib.c_str(), moduleArgs.c_str());

    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_ != nullptr, ERR_OPERATION_FAILED, "ServiceAdapter is null");
    return audioServiceAdapter_->OpenAudioPort(moduleInfo.lib, moduleArgs.c_str());
}

int32_t AudioAdapterManager::CloseAudioPort(AudioIOHandle ioHandle)
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_ != nullptr, ERR_OPERATION_FAILED, "ServiceAdapter is null");
    return audioServiceAdapter_->CloseAudioPort(ioHandle);
}

void UpdateCommonArgs(const AudioModuleInfo &audioModuleInfo, std::string &args)
{
    if (!audioModuleInfo.rate.empty()) {
        args = "rate=";
        args.append(audioModuleInfo.rate);
    }

    if (!audioModuleInfo.channels.empty()) {
        args.append(" channels=");
        args.append(audioModuleInfo.channels);
    }

    if (!audioModuleInfo.bufferSize.empty()) {
        args.append(" buffer_size=");
        args.append(audioModuleInfo.bufferSize);
    }

    if (!audioModuleInfo.format.empty()) {
        args.append(" format=");
        args.append(audioModuleInfo.format);
        AUDIO_INFO_LOG("[PolicyManager] format: %{public}s", args.c_str());
    }

    if (!audioModuleInfo.fixedLatency.empty()) {
        args.append(" fixed_latency=");
        args.append(audioModuleInfo.fixedLatency);
    }

    if (!audioModuleInfo.renderInIdleState.empty()) {
        args.append(" render_in_idle_state=");
        args.append(audioModuleInfo.renderInIdleState);
    }

    if (!audioModuleInfo.OpenMicSpeaker.empty()) {
        args.append(" open_mic_speaker=");
        args.append(audioModuleInfo.OpenMicSpeaker);
    }

    if (!audioModuleInfo.offloadEnable.empty()) {
        args.append(" offload_enable=");
        args.append(audioModuleInfo.offloadEnable);
    }
}

std::string AudioAdapterManager::GetLoopbackModuleArgs(const LoopbackModuleInfo &moduleInfo) const
{
    std::string args;

    if (moduleInfo.sink.empty() || moduleInfo.source.empty()) {
        return "";
    }

    args.append(" source=");
    args.append(moduleInfo.source);
    args.append(" sink=");
    args.append(moduleInfo.sink);
    return args;
}

// Private Members
std::string AudioAdapterManager::GetModuleArgs(const AudioModuleInfo &audioModuleInfo) const
{
    std::string args;

    if (audioModuleInfo.lib == HDI_SINK) {
        UpdateCommonArgs(audioModuleInfo, args);
        if (!audioModuleInfo.name.empty()) {
            args.append(" sink_name=");
            args.append(audioModuleInfo.name);
        }

        if (!audioModuleInfo.adapterName.empty()) {
            args.append(" adapter_name=");
            args.append(audioModuleInfo.adapterName);
        }

        if (!audioModuleInfo.className.empty()) {
            args.append(" device_class=");
            args.append(audioModuleInfo.className);
        }

        if (!audioModuleInfo.fileName.empty()) {
            args.append(" file_path=");
            args.append(audioModuleInfo.fileName);
        }
        if (!audioModuleInfo.sinkLatency.empty()) {
            args.append(" sink_latency=");
            args.append(audioModuleInfo.sinkLatency);
        }
        if (testModeOn_) {
            args.append(" test_mode_on=");
            args.append("1");
        }
        if (!audioModuleInfo.networkId.empty()) {
            args.append(" network_id=");
            args.append(audioModuleInfo.networkId);
        } else {
            args.append(" network_id=LocalDevice");
        }

        if (!audioModuleInfo.deviceType.empty()) {
            args.append(" device_type=");
            args.append(audioModuleInfo.deviceType);
        }
    } else if (audioModuleInfo.lib == HDI_SOURCE) {
        UpdateCommonArgs(audioModuleInfo, args);
        if (!audioModuleInfo.name.empty()) {
            args.append(" source_name=");
            args.append(audioModuleInfo.name);
        }

        if (!audioModuleInfo.adapterName.empty()) {
            args.append(" adapter_name=");
            args.append(audioModuleInfo.adapterName);
        }

        if (!audioModuleInfo.className.empty()) {
            args.append(" device_class=");
            args.append(audioModuleInfo.className);
        }

        if (!audioModuleInfo.fileName.empty()) {
            args.append(" file_path=");
            args.append(audioModuleInfo.fileName);
        }

        if (!audioModuleInfo.networkId.empty()) {
            args.append(" network_id=");
            args.append(audioModuleInfo.networkId);
        } else {
            args.append(" network_id=LocalDevice");
        }

        if (!audioModuleInfo.deviceType.empty()) {
            args.append(" device_type=");
            args.append(audioModuleInfo.deviceType);
        }

        if (!audioModuleInfo.sourceType.empty()) {
            args.append(" source_type=");
            args.append(audioModuleInfo.sourceType);
        }
    } else if (audioModuleInfo.lib == PIPE_SINK) {
        if (!audioModuleInfo.fileName.empty()) {
            args = "file=";
            args.append(audioModuleInfo.fileName);
        }
    } else if (audioModuleInfo.lib == PIPE_SOURCE) {
        if (!audioModuleInfo.fileName.empty()) {
            args = "file=";
            args.append(audioModuleInfo.fileName);
        }
    } else if (audioModuleInfo.lib == CLUSTER_SINK) {
        UpdateCommonArgs(audioModuleInfo, args);
        if (!audioModuleInfo.name.empty()) {
            args.append(" sink_name=");
            args.append(audioModuleInfo.name);
        }
    } else if (audioModuleInfo.lib == EFFECT_SINK) {
        UpdateCommonArgs(audioModuleInfo, args);
        if (!audioModuleInfo.name.empty()) {
            args.append(" sink_name=");
            args.append(audioModuleInfo.name);
        }
        if (!audioModuleInfo.sceneName.empty()) {
            args.append(" scene_name=");
            args.append(audioModuleInfo.sceneName);
        }
    } else if (audioModuleInfo.lib == INNER_CAPTURER_SINK || audioModuleInfo.lib == RECEIVER_SINK) {
        if (!audioModuleInfo.name.empty()) {
            args.append(" sink_name=");
            args.append(audioModuleInfo.name);
        }
    }
    return args;
}

std::string AudioAdapterManager::GetVolumeKeyForKvStore(DeviceType deviceType, AudioStreamType streamType)
{
    std::string type = GetVolumeGroupForDevice(deviceType);
    CHECK_AND_RETURN_RET_LOG(type != "", type, "Device %{public}d is not supported for kvStore", deviceType);

    switch (streamType) {
        case STREAM_MUSIC:
            return type + "_music_volume";
        case STREAM_RING:
            return type + "_ring_volume";
        case STREAM_SYSTEM:
            return type + "_system_volume";
        case STREAM_NOTIFICATION:
            return type + "_notification_volume";
        case STREAM_ALARM:
            return type + "_alarm_volume";
        case STREAM_DTMF:
            return type + "_dtmf_volume";
        case STREAM_VOICE_CALL:
        case STREAM_VOICE_COMMUNICATION:
            return type + "_voice_call_volume";
        case STREAM_VOICE_ASSISTANT:
            return type + "_voice_assistant_volume";
        case STREAM_ACCESSIBILITY:
            return type + "_accessibility_volume";
        case STREAM_ULTRASONIC:
            return type + "_ultrasonic_volume";
        case STREAM_WAKEUP:
            return type + "wakeup";
        default:
            AUDIO_ERR_LOG("GetVolumeKeyForKvStore: streamType %{public}d is not supported for kvStore", streamType);
            return "";
    }
}

std::string AudioAdapterManager::GetVolumeGroupForDevice(DeviceType deviceType)
{
    std::string volumeGroup = "";
    switch (deviceType) {
        case DEVICE_TYPE_EARPIECE:
        case DEVICE_TYPE_SPEAKER:
            volumeGroup = "build-in";
            break;
        case DEVICE_TYPE_BLUETOOTH_A2DP:
        case DEVICE_TYPE_BLUETOOTH_SCO:
            volumeGroup = "wireless";
            break;
        case DEVICE_TYPE_WIRED_HEADSET:
        case DEVICE_TYPE_USB_HEADSET:
        case DEVICE_TYPE_USB_ARM_HEADSET:
        case DEVICE_TYPE_DP:
            volumeGroup = "wired";
            break;
        case DEVICE_TYPE_REMOTE_CAST:
            volumeGroup = "remote-cast";
            break;
        default:
            AUDIO_ERR_LOG("Device %{public}d is not invalid value for volume group", deviceType);
            return "";
    }
    return volumeGroup;
}

AudioStreamType AudioAdapterManager::GetStreamIDByType(std::string streamType)
{
    AudioStreamType stream = STREAM_MUSIC;

    if (!streamType.compare(std::string("music")))
        stream = STREAM_MUSIC;
    else if (!streamType.compare(std::string("ring")))
        stream = STREAM_RING;
    else if (!streamType.compare(std::string("voice_call")))
        stream = STREAM_VOICE_CALL;
    else if (!streamType.compare(std::string("system")))
        stream = STREAM_SYSTEM;
    else if (!streamType.compare(std::string("notification")))
        stream = STREAM_NOTIFICATION;
    else if (!streamType.compare(std::string("alarm")))
        stream = STREAM_ALARM;
    else if (!streamType.compare(std::string("voice_assistant")))
        stream = STREAM_VOICE_ASSISTANT;
    else if (!streamType.compare(std::string("accessibility")))
        stream = STREAM_ACCESSIBILITY;
    else if (!streamType.compare(std::string("ultrasonic")))
        stream = STREAM_ULTRASONIC;

    return stream;
}

AudioStreamType AudioAdapterManager::GetStreamForVolumeMap(AudioStreamType streamType)
{
    switch (streamType) {
        case STREAM_VOICE_CALL:
        case STREAM_VOICE_MESSAGE:
        case STREAM_VOICE_COMMUNICATION:
            return STREAM_VOICE_CALL;
        case STREAM_RING:
        case STREAM_SYSTEM:
        case STREAM_NOTIFICATION:
        case STREAM_SYSTEM_ENFORCED:
        case STREAM_DTMF:
            return STREAM_RING;
        case STREAM_MUSIC:
        case STREAM_MEDIA:
        case STREAM_MOVIE:
        case STREAM_GAME:
        case STREAM_SPEECH:
        case STREAM_NAVIGATION:
            return STREAM_MUSIC;
        case STREAM_VOICE_ASSISTANT:
            return STREAM_VOICE_ASSISTANT;
        case STREAM_ALARM:
            return STREAM_ALARM;
        case STREAM_ACCESSIBILITY:
            return STREAM_ACCESSIBILITY;
        case STREAM_ULTRASONIC:
            return STREAM_ULTRASONIC;
        default:
            return STREAM_MUSIC;
    }
}

DeviceVolumeType AudioAdapterManager::GetDeviceCategory(DeviceType deviceType)
{
    switch (deviceType) {
        case DEVICE_TYPE_EARPIECE:
            return EARPIECE_VOLUME_TYPE;
        case DEVICE_TYPE_SPEAKER:
        case DEVICE_TYPE_FILE_SOURCE:
            return SPEAKER_VOLUME_TYPE;
        case DEVICE_TYPE_WIRED_HEADSET:
        case DEVICE_TYPE_WIRED_HEADPHONES:
        case DEVICE_TYPE_BLUETOOTH_SCO:
        case DEVICE_TYPE_BLUETOOTH_A2DP:
        case DEVICE_TYPE_USB_HEADSET:
        case DEVICE_TYPE_DP:
            return HEADSET_VOLUME_TYPE;
        default:
            return SPEAKER_VOLUME_TYPE;
    }
}

bool AudioAdapterManager::InitAudioPolicyKvStore(bool& isFirstBoot)
{
    DistributedKvDataManager manager;
    Options options;

    AppId appId;
    appId.appId = "audio_policy_manager";

    options.securityLevel = S1;
    options.createIfMissing = false;
    options.encrypt = false;
    options.autoSync = false;
    options.kvStoreType = KvStoreType::SINGLE_VERSION;
    options.area = EL1;
    options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId;

    StoreId storeId;
    storeId.storeId = "audiopolicy";
    Status status = Status::SUCCESS;

    // open and initialize kvstore instance.
    if (audioPolicyKvStore_ == nullptr) {
        uint32_t retries = 0;

        do {
            status = manager.GetSingleKvStore(options, appId, storeId, audioPolicyKvStore_);
            AUDIO_ERR_LOG("GetSingleKvStore status: %{public}d", status);
            if ((status == Status::SUCCESS) || (status == Status::INVALID_ARGUMENT) ||
                (status == Status::DATA_CORRUPTED) || (status == Status::CRYPT_ERROR)) {
                break;
            } else {
                AUDIO_ERR_LOG("InitAudioPolicyKvStore: Kvstore Connect failed! Retrying.");
                retries++;
                usleep(KVSTORE_CONNECT_RETRY_DELAY_TIME);
            }
        } while (retries <= KVSTORE_CONNECT_RETRY_COUNT);
    }

    if (audioPolicyKvStore_ == nullptr) {
        if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
            (void)manager.CloseKvStore(appId, storeId);
            status = manager.DeleteKvStore(appId, storeId, options.baseDir);
        }
        AUDIO_INFO_LOG("First Boot: Create AudioPolicyKvStore status: %{public}d", status);
        options.createIfMissing = true;
        // [create and] open and initialize kvstore instance.
        status = manager.GetSingleKvStore(options, appId, storeId, audioPolicyKvStore_);
        if (status == Status::SUCCESS) {
            isFirstBoot = true;
        } else {
            AUDIO_ERR_LOG("Create AudioPolicyKvStore Failed status: %{public}d", status);
        }
    }

    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, false,
        "InitAudioPolicyKvStore: Failed!");

    return true;
}

void AudioAdapterManager::InitVolumeMap(bool isFirstBoot)
{
    if (audioPolicyKvStore_ == nullptr) {
        AUDIO_ERR_LOG("InitVolumeMap: kvstore is null!");
        return;
    }
    if (isFirstBoot) {
        AUDIO_INFO_LOG("InitVolumeMap: Wrote default stream volumes to KvStore");
        for (auto &deviceType: DEVICE_TYPE_LIST) {
            for (auto &streamType: VOLUME_TYPE_LIST) {
                WriteVolumeToKvStore(deviceType, streamType, volumeLevelMap_[streamType]);
            }
        }
    } else {
        LoadVolumeMap();
    }
}

void AudioAdapterManager::ResetRemoteCastDeviceVolume()
{
    for (auto &streamType: VOLUME_TYPE_LIST) {
        AudioStreamType streamAlias = GetStreamForVolumeMap(streamType);
        int32_t volumeLevel = GetMaxVolumeLevel(streamAlias);
        WriteVolumeToKvStore(DEVICE_TYPE_REMOTE_CAST, streamType, volumeLevel);
    }
}

void AudioAdapterManager::InitRingerMode(bool isFirstBoot)
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr, "InitRingerMode: kvstore is null!");

    if (isFirstBoot) {
        AUDIO_INFO_LOG("InitRingerMode Wrote default ringer mode to KvStore");
        ringerMode_ = RINGER_MODE_NORMAL;
        WriteRingerModeToKvStore(RINGER_MODE_NORMAL);
    } else {
        LoadRingerMode();
    }
}

bool AudioAdapterManager::LoadVolumeFromKvStore(DeviceType deviceType, AudioStreamType streamType)
{
    std::string volumeKey = GetVolumeKeyForKvStore(deviceType, streamType);
    if (!volumeKey.compare("")) {
        AUDIO_ERR_LOG("[device %{public}d, streamType %{public}d] is not supported for kvStore",
            deviceType, streamType);
        return false;
    }

    Key key = volumeKey;
    Value value;
    Status status = audioPolicyKvStore_->Get(key, value);
    if (status == Status::SUCCESS) {
        int32_t volumeLevel = TransferByteArrayToType<int>(value.Data());
        volumeLevelMap_[streamType] = volumeLevel;
        AUDIO_DEBUG_LOG("volumeLevel %{public}d for streamType: %{public}d from kvStore",
            volumeLevel, streamType);
        return true;
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        AUDIO_ERR_LOG("load volume for streamType: %{public}d from kvStore failed, reInitKVStore", streamType);
        (void)ReInitKVStore();
    }

    return false;
}

bool AudioAdapterManager::LoadVolumeMap(void)
{
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, false,
        "LoadVolumeMap: audioPolicyKvStore_ is null!");

    for (auto &streamType: VOLUME_TYPE_LIST) {
        bool result = LoadVolumeFromKvStore(currentActiveDevice_, streamType);
        if (!result) {
            AUDIO_ERR_LOG("LoadVolumeMap: Could not load volume for streamType[%{public}d] from kvStore", streamType);
        }
    }

    return true;
}

bool AudioAdapterManager::LoadRingerMode(void)
{
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, false,
        "LoadRingerMap: audioPolicyKvStore_ is null!");

    // get ringer mode value from kvstore.
    Key key = "ringermode";
    Value value;
    Status status = audioPolicyKvStore_->Get(key, value);
    if (status == Status::SUCCESS) {
        ringerMode_ = static_cast<AudioRingerMode>(TransferByteArrayToType<int>(value.Data()));
        AUDIO_DEBUG_LOG("LoadRingerMode Ringer Mode from kvStore %{public}d", ringerMode_);
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        AUDIO_ERR_LOG("load ringerMode from kvStore %{public}d failed, reInitKVStore", ringerMode_);
        (void)ReInitKVStore();
        return false;
    }

    return true;
}

void AudioAdapterManager::WriteVolumeToKvStore(DeviceType type, AudioStreamType streamType, int32_t volumeLevel)
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr,
        "failed: audioPolicyKvStore_ is nullptr");

    std::string volumeKey = GetVolumeKeyForKvStore(type, streamType);
    if (!volumeKey.compare("")) {
        AUDIO_ERR_LOG("[device %{public}d, streamType %{public}d] is not supported for kvStore",
            type, streamType);
        return;
    }

    Key key = volumeKey;
    Value value = Value(TransferTypeToByteArray<int>(volumeLevel));

    Status status = audioPolicyKvStore_->Put(key, value);
    if (status == Status::SUCCESS) {
        AUDIO_INFO_LOG("volumeLevel %{public}d for %{public}s", volumeLevel, volumeKey.c_str());
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    } else {
        AUDIO_WARNING_LOG("Failed to write volumeLevel %{public}d for %{public}s to kvStore!",
            volumeLevel, volumeKey.c_str());
    }

    return;
}

void AudioAdapterManager::WriteRingerModeToKvStore(AudioRingerMode ringerMode)
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr,
        "WriteRingerModeToKvStore failed: audioPolicyKvStore_ is nullptr");

    Key key = "ringermode";
    Value value = Value(TransferTypeToByteArray<int>(ringerMode));

    Status status = audioPolicyKvStore_->Put(key, value);
    if (status == Status::SUCCESS) {
        AUDIO_INFO_LOG("WriteRingerModeToKvStore Wrote RingerMode:%{public}d to kvStore", ringerMode);
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    } else {
        AUDIO_WARNING_LOG("WriteRingerModeToKvStore Writing RingerMode:%{public}d to kvStore failed!", ringerMode);
    }

    const int32_t AUDIO_POLICY_SERVICE_ID = 3009;
    PowerMgr::SettingProvider& settingProvider = PowerMgr::SettingProvider::GetInstance(AUDIO_POLICY_SERVICE_ID);
    const std::string settingKey = "ringer_mode";
    ErrCode ret = settingProvider.PutIntValue(settingKey, static_cast<int32_t>(ringerMode));
    if (ret != SUCCESS) {
        AUDIO_WARNING_LOG("Failed to write ringer_mode: %{public}d to setting db! Err: %{public}d", ringerMode, ret);
    }

    return;
}

void AudioAdapterManager::InitMuteStatusMap(bool isFirstBoot)
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr, "InitMuteStatusMap: kvstore is null!");
    if (isFirstBoot) {
        AUDIO_INFO_LOG("Wrote default mute status to KvStore");
        for (auto &deviceType: DEVICE_TYPE_LIST) {
            for (auto &streamType: VOLUME_TYPE_LIST) {
                WriteMuteStatusToKvStore(deviceType, streamType, 0);
            }
        }
    } else {
        LoadMuteStatusMap();
    }
}


bool AudioAdapterManager::LoadMuteStatusMap(void)
{
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, false,
        "LoadMuteStatusMap: audioPolicyKvStore_ is null");

    for (auto &streamType: VOLUME_TYPE_LIST) {
        bool result = LoadMuteStatusFromKvStore(currentActiveDevice_, streamType);
        if (!result) {
            AUDIO_WARNING_LOG("Could not load mute status for stream type %{public}d from kvStore", streamType);
        }
    }
    return true;
}

bool AudioAdapterManager::LoadMuteStatusFromKvStore(DeviceType deviceType, AudioStreamType streamType)
{
    std::string muteKey = GetMuteKeyForKvStore(deviceType, streamType);
    if (!muteKey.compare("")) {
        AUDIO_ERR_LOG("[device %{public}d, streamType %{public}d] is not supported for "\
            "kvStore", deviceType, streamType);
        return false;
    }

    Key key = muteKey;
    Value value;

    Status status = audioPolicyKvStore_->Get(key, value);
    if (status == Status::SUCCESS) {
        bool muteStatus = TransferByteArrayToType<int>(value.Data());
        muteStatusMap_[streamType] = muteStatus;
        return true;
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    }

    return false;
}

std::string AudioAdapterManager::GetMuteKeyForKvStore(DeviceType deviceType, AudioStreamType streamType)
{
    std::string type = "";
    switch (deviceType) {
        case DEVICE_TYPE_EARPIECE:
        case DEVICE_TYPE_SPEAKER:
            type = "build-in";
            break;
        case DEVICE_TYPE_BLUETOOTH_A2DP:
        case DEVICE_TYPE_BLUETOOTH_SCO:
            type = "wireless";
            break;
        case DEVICE_TYPE_WIRED_HEADSET:
        case DEVICE_TYPE_USB_HEADSET:
        case DEVICE_TYPE_DP:
        case DEVICE_TYPE_USB_ARM_HEADSET:
            type = "wired";
            break;
        default:
            AUDIO_ERR_LOG("GetMuteKeyForKvStore: device %{public}d is not supported for kvStore", deviceType);
            return "";
    }

    switch (streamType) {
        case STREAM_MUSIC:
            return type + "_music_mute_status";
        case STREAM_RING:
            return type + "_ring_mute_status";
        case STREAM_SYSTEM:
            return type + "_system_mute_status";
        case STREAM_NOTIFICATION:
            return type + "_notification_mute_status";
        case STREAM_ALARM:
            return type + "_alarm_mute_status";
        case STREAM_DTMF:
            return type + "_dtmf_mute_status";
        case STREAM_VOICE_CALL:
        case STREAM_VOICE_COMMUNICATION:
            return type + "_voice_call_mute_status";
        case STREAM_VOICE_ASSISTANT:
            return type + "_voice_assistant_mute_status";
        case STREAM_ACCESSIBILITY:
            return type + "_accessibility_mute_status";
        case STREAM_ULTRASONIC:
            return type + "_unltrasonic_mute_status";
        default:
            AUDIO_ERR_LOG("GetMuteKeyForKvStore: streamType %{public}d is not supported for kvStore", streamType);
            return "";
    }
}

void AudioAdapterManager::WriteMuteStatusToKvStore(DeviceType deviceType, AudioStreamType streamType,
    bool muteStatus)
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr,
        "WriteMuteStatusToKvStore failed: audioPolicyKvStore_ is nullptr");

    std::string muteKey = GetMuteKeyForKvStore(deviceType, streamType);
    if (!muteKey.compare("")) {
        AUDIO_ERR_LOG("WriteMuteStatusToKvStore: [device %{public}d, streamType %{public}d] is not supported for "\
            "kvStore", deviceType, streamType);
        return;
    }

    Key key = muteKey;
    Value value = Value(TransferTypeToByteArray<int>(muteStatus));

    Status status = audioPolicyKvStore_->Put(key, value);
    if (status == Status::SUCCESS) {
        AUDIO_INFO_LOG("WriteMuteStatusToKvStore: muteStatus %{public}d for %{public}s", muteStatus, muteKey.c_str());
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    } else {
        AUDIO_WARNING_LOG("WriteMuteStatusToKvStore: Failed to write muteStatus %{public}d for %{public}s to kvStore!",
            muteStatus, muteKey.c_str());
    }

    return;
}

float AudioAdapterManager::CalculateVolumeDb(int32_t volumeLevel)
{
    float value = static_cast<float>(volumeLevel) / MAX_VOLUME_LEVEL;
    float roundValue = static_cast<int>(value * CONST_FACTOR);

    return static_cast<float>(roundValue) / CONST_FACTOR;
}

void AudioAdapterManager::InitSystemSoundUriMap()
{
    CHECK_AND_RETURN_LOG(audioPolicyKvStore_ != nullptr, "audioPolicyKvStore_ is null");
    for (auto &key: SYSTEM_SOUND_KEY_LIST) {
        std::string systemSoundUri = LoadSystemSoundUriFromKvStore(key);
        if (systemSoundUri == "") {
            AUDIO_WARNING_LOG("Could not load system sound uri for %{public}s from kvStore", key.c_str());
        }
        systemSoundUriMap_[key] = systemSoundUri;
    }
}

int32_t AudioAdapterManager::SetSystemSoundUri(const std::string &key, const std::string &uri)
{
    auto pos = std::find(SYSTEM_SOUND_KEY_LIST.begin(), SYSTEM_SOUND_KEY_LIST.end(), key);
    if (pos == SYSTEM_SOUND_KEY_LIST.end()) {
        AUDIO_ERR_LOG("Invalid key %{public}s for system sound uri", key.c_str());
        return ERR_INVALID_PARAM;
    }
    std::lock_guard<std::mutex> lock(systemSoundMutex_);
    if (systemSoundUriMap_.size() == 0) {
        InitSystemSoundUriMap();
        CHECK_AND_RETURN_RET_LOG(systemSoundUriMap_.size() != 0, ERR_OPERATION_FAILED,
            "Failed to init system sound uri map.");
    }
    systemSoundUriMap_[key] = uri;
    return WriteSystemSoundUriToKvStore(key, uri);
}

std::string AudioAdapterManager::GetSystemSoundUri(const std::string &key)
{
    auto pos = std::find(SYSTEM_SOUND_KEY_LIST.begin(), SYSTEM_SOUND_KEY_LIST.end(), key);
    if (pos == SYSTEM_SOUND_KEY_LIST.end()) {
        AUDIO_ERR_LOG("Invalid key %{public}s for system sound uri", key.c_str());
        return "";
    }
    std::lock_guard<std::mutex> lock(systemSoundMutex_);
    if (systemSoundUriMap_.size() == 0) {
        InitSystemSoundUriMap();
        CHECK_AND_RETURN_RET_LOG(systemSoundUriMap_.size() != 0, "",
            "Failed to init system sound uri map.");
    }
    return systemSoundUriMap_[key];
}

int32_t AudioAdapterManager::WriteSystemSoundUriToKvStore(const std::string &key, const std::string &uri)
{
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, ERROR,
        "WriteSystemSoundUriToKvStore failed: audioPolicyKvStore_ is nullptr");

    Status status = audioPolicyKvStore_->Put(key, uri);
    if (status == Status::SUCCESS) {
        AUDIO_INFO_LOG("WriteSystemSoundUriToKvStore: Wrote [%{public}s]: [%{public}s] to kvStore",
            key.c_str(), uri.c_str());
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    } else {
        AUDIO_WARNING_LOG("WriteSystemSoundUriToKvStore: Writing [%{public}s]: [%{public}s] to kvStore failed",
            key.c_str(), uri.c_str());
    }

    return SUCCESS;
}

std::string AudioAdapterManager::LoadSystemSoundUriFromKvStore(const std::string &key)
{
    std::string uri = "";
    CHECK_AND_RETURN_RET_LOG(audioPolicyKvStore_ != nullptr, uri,
        "LoadSystemSoundUriFromKvStore failed: audioPolicyKvStore_ is nullptr");
    Value value;
    Status status = audioPolicyKvStore_->Get(key, value);
    if (status == Status::SUCCESS) {
        uri = value.ToString();
    } else if (status == Status::DATA_CORRUPTED || status == Status::CRYPT_ERROR) {
        (void)ReInitKVStore();
    }
    AUDIO_INFO_LOG("LoadSystemSoundUriFromKvStore:: [%{public}s]: [%{public}s]", key.c_str(), uri.c_str());
    return uri;
}

float AudioAdapterManager::GetMinStreamVolume() const
{
    return MIN_STREAM_VOLUME;
}

float AudioAdapterManager::GetMaxStreamVolume() const
{
    return MAX_STREAM_VOLUME;
}

int32_t AudioAdapterManager::UpdateSwapDeviceStatus()
{
    CHECK_AND_RETURN_RET_LOG(audioServiceAdapter_, ERR_OPERATION_FAILED,
        "UpdateSwapDeviceStatus audio adapter null");
    return audioServiceAdapter_->UpdateSwapDeviceStatus();
}

bool AudioAdapterManager::IsVolumeUnadjustable()
{
    return isVolumeUnadjustable_;
}

float AudioAdapterManager::GetSystemVolumeInDb(AudioVolumeType volumeType, int32_t volumeLevel, DeviceType deviceType)
{
    AUDIO_DEBUG_LOG("GetSystemVolumeInDb for volumeType: %{public}d deviceType:%{public}d volumeLevel:%{public}d",
        volumeType, deviceType, volumeLevel);
    if (useNonlinearAlgo_) {
        getSystemVolumeInDb_ = CalculateVolumeDbNonlinear(volumeType, deviceType, volumeLevel);
    } else {
        getSystemVolumeInDb_ = CalculateVolumeDb(volumeLevel);
    }
    AUDIO_DEBUG_LOG("Get system volume in db success %{public}f", getSystemVolumeInDb_);

    return getSystemVolumeInDb_;
}

uint32_t AudioAdapterManager::GetPositionInVolumePoints(std::vector<VolumePoint> &volumePoints, int32_t idx)
{
    int32_t leftPos = 0;
    int32_t rightPos = volumePoints.size() - 1;
    while (leftPos <= rightPos) {
        int32_t midPos = leftPos + (rightPos - leftPos)/NUMBER_TWO;
        int32_t c = volumePoints[midPos].index - idx;
        if (c == 0) {
            leftPos = midPos;
            break;
        } else if (c < 0) {
            leftPos = midPos + 1;
        } else {
            rightPos = midPos - 1;
        }
    }
    return leftPos;
}

float AudioAdapterManager::CalculateVolumeDbNonlinear(AudioStreamType streamType,
    DeviceType deviceType, int32_t volumeLevel)
{
    AUDIO_DEBUG_LOG("CalculateVolumeDbNonlinear for stream: %{public}d devicetype:%{public}d volumeLevel:%{public}d",
        streamType, deviceType, volumeLevel);
    AudioStreamType streamAlias = GetStreamForVolumeMap(streamType);
    int32_t minVolIndex = GetMinVolumeLevel(streamAlias);
    int32_t maxVolIndex = GetMaxVolumeLevel(streamAlias);
    if (minVolIndex < 0 || maxVolIndex < 0 || minVolIndex >= maxVolIndex) {
        return 0.0f;
    }
    if (volumeLevel < minVolIndex) {
        volumeLevel = minVolIndex;
    }
    if (volumeLevel > maxVolIndex) {
        volumeLevel = maxVolIndex;
    }

    DeviceVolumeType deviceCategory = GetDeviceCategory(deviceType);
    std::vector<VolumePoint> volumePoints;
    GetVolumePoints(streamAlias, deviceCategory, volumePoints);
    int32_t pointSize = volumePoints.size();

    int32_t volSteps = 1 + volumePoints[pointSize - 1].index - volumePoints[0].index;
    int32_t idxRatio = (volSteps * (volumeLevel - minVolIndex)) / (maxVolIndex - minVolIndex);
    int32_t position = GetPositionInVolumePoints(volumePoints, idxRatio);
    if (position == 0) {
        if (minVolIndex != 0) {
            AUDIO_INFO_LOG("Min volume index not zero, use min db: %{public}0.1f", volumePoints[0].dbValue / 100.0f);
            return exp((volumePoints[0].dbValue / 100.0f) * 0.115129f);
        }
        AUDIO_DEBUG_LOG("position = 0, return 0.0");
        return 0.0f;
    } else if (position >= pointSize) {
        AUDIO_DEBUG_LOG("position > pointSize, return %{public}f",
            exp(volumePoints[pointSize - 1].dbValue * 0.115129f));
        return exp((volumePoints[pointSize - 1].dbValue / 100.0f) * 0.115129f);
    }
    float indexFactor = ((float)(idxRatio - volumePoints[position-1].index)) /
        (float(volumePoints[position].index - volumePoints[position-1].index));

    float dbValue = (volumePoints[position-1].dbValue / 100.0f) +
        indexFactor * ((volumePoints[position].dbValue / 100.0f) - (volumePoints[position-1].dbValue / 100.0f));

    AUDIO_DEBUG_LOG(" index=[%{public}d, %{public}d, %{public}d]"
        "db=[%{public}0.1f %{public}0.1f %{public}0.1f] factor=[%{public}f]",
        volumePoints[position-1].index, idxRatio, volumePoints[position].index,
        ((float)volumePoints[position - 1].dbValue / 100.0f), dbValue,
        ((float)volumePoints[position].dbValue / 100.0f), exp(dbValue * 0.115129f));

    return exp(dbValue * 0.115129f);
}

void AudioAdapterManager::InitVolumeMapIndex()
{
    useNonlinearAlgo_ = 0;
    for (auto streamType : VOLUME_TYPE_LIST) {
        minVolumeIndexMap_[streamType] = MIN_VOLUME_LEVEL;
        maxVolumeIndexMap_[streamType] = MAX_VOLUME_LEVEL;
        volumeLevelMap_[streamType] = DEFAULT_VOLUME_LEVEL;
        AUDIO_DEBUG_LOG("streamType %{public}d index = [%{public}d, %{public}d, %{public}d]",
            streamType, minVolumeIndexMap_[streamType],
            maxVolumeIndexMap_[streamType], volumeLevelMap_[streamType]);
    }

    volumeLevelMap_[STREAM_ULTRASONIC] = MAX_VOLUME_LEVEL;
}

void AudioAdapterManager::UpdateVolumeMapIndex()
{
    for (auto streamVolInfoPair : streamVolumeInfos_) {
        auto streamVolInfo = streamVolInfoPair.second;
        minVolumeIndexMap_[streamVolInfo->streamType] = streamVolInfo->minLevel;
        maxVolumeIndexMap_[streamVolInfo->streamType] = streamVolInfo->maxLevel;
        volumeLevelMap_[streamVolInfo->streamType] = streamVolInfo->defaultLevel;
        AUDIO_DEBUG_LOG("update streamType %{public}d index = [%{public}d, %{public}d, %{public}d]",
            streamVolInfo->streamType, minVolumeIndexMap_[streamVolInfo->streamType],
            maxVolumeIndexMap_[streamVolInfo->streamType], volumeLevelMap_[streamVolInfo->streamType]);
    }
}

void AudioAdapterManager::GetVolumePoints(AudioVolumeType streamType, DeviceVolumeType deviceType,
    std::vector<VolumePoint> &volumePoints)
{
    auto streamVolInfo = streamVolumeInfos_.find(streamType);
    auto deviceVolInfo = streamVolInfo->second->deviceVolumeInfos.find(deviceType);
    volumePoints = deviceVolInfo->second->volumePoints;
}

void AudioAdapterManager::GetStreamVolumeInfoMap(StreamVolumeInfoMap &streamVolumeInfos)
{
    streamVolumeInfos = streamVolumeInfos_;
}

DeviceType AudioAdapterManager::GetActiveDevice()
{
    return currentActiveDevice_;
}

void AudioAdapterManager::SetAbsVolumeScene(bool isAbsVolumeScene)
{
    isAbsVolumeScene_ = isAbsVolumeScene;
}

bool AudioAdapterManager::IsAbsVolumeScene() const
{
    return isAbsVolumeScene_;
}
} // namespace AudioStandard
} // namespace OHOS
